#include <fcntl.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/signal.h>
#include <sys/select.h>
#include <sys/time.h>
#include <sys/wait.h>
#include <unistd.h>
#include <sys/msg.h>
#include <sys/ipc.h>
#include <pthread.h>

#include "../notifyADT/notifyADT.h"
#include "../include/shm_client.h"
#include "../../common/include/commonSHM.h"
#include "../../common/include/filesystem.h"
#include "../../common/include/split.h"
#include "../../common/include/general.h"
#include "../include/client.h"
#include "../../common/include/common.h"
#include "../../common/include/sem.h"

#define PUB_KEY 500
#define SHMSZ 1024

int msgForClient (shmADT s);



int cliID;
char usr_name[MAX_NAME_LEN] = {0};

shmADT pub;
shmADT privShm;

/* Externs de client.c */
extern int logged;
extern watchD w;
extern char *syncPath;
extern char splitVal;
extern pthread_t threads[SPLITS_QUANTITY];
extern int sons[SPLITS_QUANTITY];
extern int doLS;
extern char lastComm[FILE_LEN];


int
mainSM (void)
{

    logged = 0;

    if((pub = open_conn_shm(PUB_KEY, 1)) == NULL)
    {
        perror("shmget");
        exit(1);
    }

    /* Handlers de SIGS */
    (void)signal(SIGINT, sighandINTSM);

    cliID = getpid();
    readCommandsSM();

    if (close_conn_shm (pub))
        fatal ("shared memory close failed\n");

    exit(0);
}

int nombreSM (void)
{
    char name[50] = {0};
    char msg[BUF_LEN] = {0};
    int len = 0, ans, aux, splitRet;

    fprintf (stdout, "\nInsert your name: ");
    getLine (name, MAX_COMMAND_LEN, stdin);

    strcpy(usr_name, name);

    if((privShm = open_conn_shm(cliID, 1)) == NULL)
    {
        perror("open shared memory");
        close_conn_shm(pub);
        /*TODO: exit que corresponda */
//        exit(1);
    }

    sprintf(msg, "0,%d,2,%d,%d,%s", logged, strlen(name), getShmKey(privShm), name);

    len = strlen(msg);
    send_data_shm(pub, msg, len);
    

    while(!msgForClient (privShm))
        ;
        
	clrtext(msg, BUF_LEN);
    rcv_data_shm(privShm, msg);
    printf("msg recibido: %s\n", msg);
    sscanf(msg, "%d,%d,%d", &aux, &ans, &logged);
    printf("msg received: %d\n", ans);

    clrtext(msg, BUF_LEN);
    sprintf(msg, "0,%d",COM_ACK);
    len = strlen(msg);
    send_data_shm(privShm, msg, len);

    /*Se splitea dependiendo de los parámetros.*/
    if (splitVal == 't')
        splitRet = split(listenSrvSM, NULL, (void *)&threads[LISTSRV_SPLIT],
                    splitVal, endCiclesSM);
    else
        splitRet = split(listenSrvSM, NULL, (void *)&sons[LISTSRV_SPLIT],
                    splitVal, endCiclesSM);

    if ( splitRet != 1)
        fatal(  "ERROR: Split failed.\n"
                "SOLUTION: Check SPLITS_QUANTITY.\n");
    return 1;
}

void *
listenSrvSM (void *parmsLS)
{
    fd_set master_set, working_set;
    char ch;
    struct timeval tw, tm;
    char msg[SHMSZ] = {0};

    tm.tv_sec  = SEC_TIMEOUT;
    tm.tv_usec = 0;
    FD_ZERO(&master_set);

    /*Inicializo w*/
    w.waList = NULL;

    if ((w.fd = notify()) == -1)
    {
        fprintf(stderr, "Error al llamar a notify()\n");
        return NULL;
    }

    FD_SET(w.fd, &master_set);

    while (doLS)
    {
        memcpy(&working_set, &master_set, sizeof(master_set));
        memcpy(&tw, &tm, sizeof(struct timeval));

        if(msgForClient(privShm))
        {
        	clrtext(msg, SHMSZ);
            rcv_data_shm(privShm, msg);
            takeSrvSM(msg);
        }

        if( select(w.fd + 1, &working_set, (fd_set *)0, (fd_set *)0, &tw) < 0)
        {
            if (errno == EINTR)
                continue;
            else
                fatal ("select failed\n");
        }

        if (FD_ISSET (0, &working_set))
        {
            read(0, &ch, 1);
            printf("%c\n", ch);
        }

        if (FD_ISSET (w.fd, &working_set))
        {
            makeCommitSM();
        }
    }

    return NULL;
}


void readCommandsSM (void)
{
    int i;
    int ret = 1;
    char command[MAX_COMMAND_LEN+1] = {0};

    char * commands[] = {"nombre", "lista", "agregar", "remover", "salir", "commit"};

    int cant_comms = sizeof(commands) / sizeof(commands[0]);

    int (*pFunct[]) (void)= {nombreSM, listaSM, agregarSM,
                                    removerSM, salirSM, commitSM};

    fprintf (stdout, "\n<>: ");
    getLine (command, MAX_COMMAND_LEN, stdin);

    for (i=0 ; i < cant_comms+1 ; i++)
    {
        if (i == cant_comms)
        {
           fprintf (stdout, "\nError: Invalid command\n<>: ");
           getLine (command, MAX_COMMAND_LEN, stdin);
           i = -1;
        }
        else if (strcmp (command, commands[i]) == 0)
        {
            if(i == QUIT_POS)
            {
                closeAllSM();
                exit(0);
                return;
            }

            if (i == NAME_POS)
            {
                ret = pFunct[i] ();
            }
            else
            {
                if (!logged)
                {
                    fprintf (stdout, "Not logged in.\n");
                }
                else
                {
                    ret = pFunct[i] ();
                }
            }

            /* HACK: Si la funcion devuelve -1 salir */
            if(ret == -1)
                exit(0);

            fprintf (stdout, "\n<>: ");
            getLine (command, MAX_COMMAND_LEN, stdin);
            i = -1;
        }
    }

    return;
}

int takeSrvSM (char * msg)
{
    int comm;
    sscanf(msg, "1,%d", &comm);

    switch(comm)
    {
        case COM_SND_DIRLIST:
                printf("LISTA!\n");
                atenderListaSM(msg);
                break;

            case COM_SND_FILES:
                printf("ADD!\n");
                atenderAddSM(msg);
                break;

            case COM_RCV_COMMIT:
                printf("COMMIT!\n");
                atenderCommitSM(msg);
                break;

            case WILL_UPDATE:
                printf("WILL UPDATE!\n");
                atenderWillUpdateSM(msg);
                break;

            case COM_SND_COMMIT:
                printf("UPDATE!\n");
                atenderUpdateSM(msg);
                break;

            case COM_RMV_OK:
                printf("REMOVE OK!\n");
                atenderRemoveSM(msg);
                break;

            case COM_LOGOUT:
                printf("LOGOUT!\n");
                exit(0);

            case COMMIT_OK:
                printf("COMMIT (del) OK!\n");
                atenderCommOKSM(msg);
                break;

            case DIR_ERR:
                printf("Invalid dir!\n");
                break;

            case IS_SYNC:
                printf("Dir already syncronized\n");
                break;

            case IS_BUSY:
                printf("Performing another action, please try later\n");
                return -1;
                break;

            case COM_ERR:
                printf("Error occurred\n");
                break;

            default :
                printf("Command not understood\n");
        }

    return 1;
}

void atenderListaSM (char * msg)
{
    char dir[50] = {0};
    int comm, name_len, index = 1;
    char r_msg[SHMSZ] = {0};
    char aux_msg[SHMSZ] = {0};


    sprintf(r_msg, "0,%d", COM_ACK);
    send_data_shm(privShm, r_msg, strlen(r_msg));

    while(!msgForClient(privShm))
        ;

    rcv_data_shm(privShm, r_msg);
    sscanf(r_msg, "1,%d,%d,%s", &comm, &name_len, dir);

    while(comm != COM_END)
    {
        printf("%2d %s\n", index++, dir);

        while(name_len)
        {
            dir[--name_len] = 0;
        }

        sprintf(r_msg, "0,%d", COM_ACK);
        send_data_shm(privShm, r_msg, strlen(r_msg));

        while(!msgForClient(privShm))
            ;
        clrtext(r_msg, SHMSZ);
        rcv_data_shm(privShm, r_msg);
        
        clrtext(aux_msg, SHMSZ);
        sscanf(r_msg, "1,%d,%s", &comm, aux_msg);
        if(comm != COM_END)
            sscanf(aux_msg, "%d,%s", &name_len, dir);
    }

    clrtext(r_msg, SHMSZ);
    sprintf(r_msg, "0,%d", COM_ACK);
    send_data_shm(privShm, r_msg, strlen(r_msg));

    return;
}

void atenderAddSM (char * msg)
{
    char r_msg[SHMSZ + 1] = {0};
    char path[MAX_DIR_LEN] = {0};
    char aux_path[MAX_DIR_LEN] = {0};
    char currPath[FILE_LEN];
    int len,  com, size, nread;
    FILE *pfile;
    int aux_size;

    sscanf(msg, "1,%d,%d,%s", &com, &size, path);
    len = strlen(path);
    path[size] = '\0';


    sprintf(currPath, "%s/%s", syncPath, path);
    if (!startFolder(currPath))
    {
        fatal ("Couldn't startFolder.\n");
    }

    sprintf(r_msg, "0,%d",COM_ACK);
    send_data_shm(privShm, r_msg, strlen(r_msg));

    while(!msgForClient(privShm))
        ;
        
	clrtext(r_msg, SHMSZ);
    rcv_data_shm(privShm, r_msg);
    sscanf(r_msg, "1,%d,%d,%s", &com, &size, path);
    sscanf(path, "%d,%s", &size, path);

    while(com != COM_END)
    {

        printf("SIZE: %d    PATH: %s\n", size, path);

        if (size == -1)
        {
            mkdir(path, 0744);
            sprintf(r_msg, "%d,%d", 0, COM_ACK);
            send_data_shm(privShm, r_msg, strlen(r_msg));
        }
        else
        {
            if((pfile = fopen(path, "w")) == NULL)
                fatal ("Error creating file\n");

            nread = 0;
            clrtext(r_msg, SHMSZ);
            sprintf(r_msg, "%d,%d", 0, COM_ACK);
            send_data_shm(privShm, r_msg, strlen(r_msg));

            while(size > 0)
            {
                if (size >= SHMSZ)
                    nread = SHMSZ;
                else
                    nread = size;

                while(!msgForClient(privShm))
                    ;

                clrtext(r_msg, SHMSZ + 1);
                rcv_data_shm(privShm, r_msg);
                
                if((fwrite(r_msg + 1, 1, nread, pfile))< nread)
                {
                	clrtext(r_msg, SHMSZ + 1);
                    sprintf(r_msg, "0,%d", COM_ERR);
                    fatal("File write failed\n");
                }

                clrtext(r_msg, SHMSZ + 1);
                sprintf(r_msg, "0,%d", COM_ACK);
                size -= nread;
                send_data_shm(privShm, r_msg, strlen(r_msg));
            }

            if((fclose(pfile)) == EOF)
                fatal("file close failed\n");
        }

        while(!msgForClient(privShm))
            usleep(100);

        clrtext(r_msg, SHMSZ+1);
        rcv_data_shm(privShm, r_msg);

        sscanf(r_msg, "1,%d,%s", &com, aux_path);
        printf("R_MSG: %s\n", r_msg);
        if (com != COM_END)
        {
            clrtext(path, MAX_DIR_LEN);
            sscanf(aux_path, "%d,%d,%s", &aux_size, &size, path);
        }
    }
    
    clrtext(r_msg, SHMSZ+1);
    sprintf(r_msg, "0,%d", COM_ACK);
    send_data_shm(privShm, r_msg, strlen(r_msg));

    printf("fd: %d\n", w.fd);
    if(setWatchs(currPath, &w) == -1)
    {
        fprintf(stderr, "Error en setWatchs\n");
        return ;
    }

    return;
}
void atenderCommOKSM(char * msg)
{
    char out_msg[MSGSIZE+1] = {0};

    sprintf(out_msg, "0,%d",COM_END);
    send_data_shm(privShm, out_msg, strlen(out_msg));
    printf("OKOKOK\n");
    sleep(2);
    return ;
}

void atenderCommitSM (char * msg)
{
    int size, com;
    char path[FILE_LEN] = {0};
    int back;
    char out_msg[MSGSIZE+1] = {0};
    char r_msg[SHMSZ] = {0};


    sscanf(msg, "1,%d,%d,%s", &com, &size, path);

    sprintf(out_msg, "0,%d",COM_ACK);
    send_data_shm(privShm, out_msg, strlen(out_msg));

    while(!msgForClient(privShm))
        ;

    clrtext(r_msg, SHMSZ);
    rcv_data_shm(privShm, r_msg);

    sscanf(r_msg, "1,%d", &back);


    if (back != COM_ACK)
    {
        fatal("Error received\n");
        return;
    }

    if (send_file_shm (privShm, privShm, path, 0, 0) < 0)
    {
        printf ("%s not commited\n", path);
        return ;
    }

    while(!msgForClient(privShm))
        ;
    clrtext(r_msg, SHMSZ);
    rcv_data_shm(privShm, r_msg);

    sscanf(r_msg, "1,%d", &back);


    if (back != COM_ACK)
    {
        fatal("Error received\n");
        return;
    }

    clrtext(out_msg, MSGSIZE +1);
    sprintf(out_msg, "0,%d",COM_END);
    send_data_shm(privShm, out_msg, strlen(out_msg));
    printf("END: %s\n", out_msg);

    sleep(2);
    printf("ENDAA\n");

    return ;
}

void atenderWillUpdateSM (char * msg)
{
    char  minePath[FILE_LEN] = {0};
    char dir[50] = {0};
    int move, size;
    char out_msg[MSGSIZE +1] = {0};

    sscanf(msg, "1,%d,%d,%s", &move, &size, dir);
    printf("DIR: %s\n", dir);

    sprintf(minePath, "%s.mine", dir);

    cp(dir, minePath);

    printf("Conflicts occured, fix before commiting\n");

    sprintf(out_msg, "0,%d",COM_END);
    send_data_shm(privShm, out_msg, strlen(out_msg));

    return ;
}

void atenderUpdateSM (char * msg)
{
    char msgbuf[100] = {0};
    char currPath[FILE_LEN];
    char dir[50] = {0};
    char aux_dir[MAX_DIR_LEN] = {0};
    int comm, nread, path_size, size;
    char path[100] = {0};
    FILE * pfile;
    int type = 5;
    int move;
    char out_msg[SHMSZ+1] = {0};
    char aux_msg[MSGSIZE+1] = {0};
    char r_msg[SHMSZ + 1] = {0};
    char newpath[100] = {0};


    sscanf(msg, "1,%d,%d,%s", &comm, &size, aux_dir);

    getDirType (aux_dir, dir, &type);

    sprintf(currPath,"%s/%s",syncPath, dir);

    printf("DIR: %s     type: %d\n", dir, type);

    sprintf(out_msg, "0,%d", COM_ACK);
    size = strlen(out_msg);
    send_data_shm(privShm, out_msg, strlen(out_msg));


    if (type == ADD_MOD)
    {
        while(!msgForClient(privShm))
            ;

        rcv_data_shm(privShm, aux_msg);

        move = getNum_shm(aux_msg, &comm);
        move += getNum_shm(aux_msg, &comm);
        move += getNum_shm(aux_msg + move, &path_size);

        sprintf(msgbuf, "%s", aux_msg + move);
        msgbuf[path_size] = 0;
        sscanf (msgbuf, "%d,%s", &size, path);
        sprintf(newpath, "%s.new", path);

        printf("Path: %s    New: %s\n", path, newpath);
        
        clrtext(out_msg, SHMSZ);

        /*it's a dir*/
        if (size == -1)
        {
            if (mkdir(path, 0744) == -1)
            {
                printf("ERROR: creating dir: %s\n", path);
                return ;
            }
            sprintf(lastComm, "%s", path);
            
            sprintf(out_msg, "0,%d", COM_ACK);
            size = strlen(out_msg);
            send_data_shm(privShm, out_msg, strlen(out_msg));
        }
        else
        {
            if((pfile = fopen(newpath, "w")) == NULL)
            {
                fatal ("Error creating file\n");
                return ;
            }

            nread = 0;
            sprintf(out_msg, "0,%d", COM_ACK);
            send_data_shm(privShm, out_msg, strlen(out_msg));
            while (size > 0)
            {
                if (size >= BUF_SIZE)
                    nread = BUF_SIZE;
                else
                    nread = size;

                while(!msgForClient(privShm))
                    ;

                clrtext(r_msg, SHMSZ + 1);
                rcv_data_shm(privShm, r_msg);
                if((fwrite(r_msg + 1, 1, nread, pfile))< nread)
                {
                    sprintf(r_msg, "0,%d", COM_ERR);
                    fatal("File write failed\n");
                }
                
                clrtext(out_msg, SHMSZ);
                sprintf(out_msg, "0,%d", COM_ACK);
                size = strlen(out_msg);
                send_data_shm(privShm, out_msg, strlen(out_msg));

                size -= nread;

            }

            if ((fclose (pfile)) == EOF)
            {
                printf ("file close failed\n");
                return ;
            }
            if (rename(newpath, path) != 0)
            {
                    printf ("Error renaming %s\n", newpath);
                    return;
            }
        }
    }
    else if(type == DEL_COMMIT)
    {
        sprintf(newpath, "%s.new", dir);

        if (remove(dir) != 0)
        {
                //sndFifoAns(fifo_serv, COM_ERR); TODO:
        }
        else
                //sndFifoAns(fifo_serv, COM_ACK); TODO:
            sprintf(lastComm, "%s", dir);
    }

    else if(type == DEL_DIR_COMMIT)
    {

        if (rmdir(dir) != 0)
        {
                //sndFifoAns(fifo_serv, COM_ERR);
        }
        else
                //sndFifoAns(fifo_serv, COM_ACK);
            sprintf(lastComm, "%s", dir);
    }

    while(!msgForClient(privShm))
        ;

    clrtext(r_msg, SHMSZ + 1);
    rcv_data_shm(privShm, r_msg);
    printf("ENDCLI: %s\n", r_msg);

    r_msg[0] = '0';
    send_data_shm(privShm, r_msg, strlen(r_msg));
    printf("ENDCLI2: %s\n", r_msg);
    return;

}

int makeCommitSM (void)
{
    int i = 0, len, flag, resp;
    char buf[BUF_LEN_NOTIF] = {0};
    char * path = NULL;
    struct inotify_event *event;
    char completePath[FILE_LEN] = {0};

    len = read(w.fd, buf, BUF_LEN_NOTIF);
    if(len == -1)
    {
        fprintf(stderr, "Error en read\n");
        return 0;
    }

    i = 0;

    while (i < len)
    {
        flag = 0;

        event = (struct inotify_event *) &buf[i];
        if (event->len == 0)
        {
            i += EVENT_SIZE + event->len;
            continue;
        }

        if ((path = getWatchCompletePath(event, &w)) == NULL)
        {
            i += EVENT_SIZE + event->len;
            continue;
        }

        sprintf(completePath, "%s/%s", path, event->name);

        free(path);
        path = NULL;

        if( (strcmp(fileExt(event->name), ".new") != 0) &&
            (strcmp(fileExt(event->name), ".old") != 0) &&
            (strcmp(fileExt(event->name), ".mine") != 0) )
        {
            if(strcmp(completePath, lastComm) != 0)
            {
                switch(event->mask)
                {
                    case MOVE_TO_MASK:
                    case ADD_DIR:
                    case ADD_MASK:
                        do{
                            resp = commit_fileSM(pub, completePath, 1);
                            if (resp)
                                while((flag = listenSM()) == 0);
                         }while(flag == -1);
                        break;

                    case MOD_MASK:
                        do{
                            resp = commit_fileSM(pub, completePath, 1);
                            if (resp)
                                while((flag = listenSM()) == 0);
                        }while( flag == -1);
                        break;

                    case DEL_DIR:
                        do{
                            resp = commit_fileSM(pub, completePath, 2);
                            if (resp)
                                while((flag = listenSM()) == 0);
                        }while(flag == -1);
                        i += EVENT_SIZE + event->len;
                        continue;
                        break;

                    case MOVE_FROM_MASK:
                    case DEL_MASK:
                        do{
                            resp = commit_fileSM(pub, completePath, 0);
                            if (resp)
                                while((flag = listenSM()) == 0);
                        }while(flag == -1);
                        break;


                    default:
                        printf("Error en makeCommit con mask = %u\n", event->mask);
                        break;
                }
            }
            else
                clrtext(lastComm, FILE_LEN);
        }
        else
        {
            int k = strlen(completePath) - 1;
            sprintf(lastComm, "%s", completePath);
            while(lastComm[k] != '.' && k)
                k--;
            if (k)
                lastComm[k] = 0;
        }
        if(event->mask != DEL_DIR)
        {
            if(update(&w, event) == -1)
            {
                fprintf(stderr, "Error en upgrade\n");
            }
        }
        i += EVENT_SIZE + event->len;

    }

    return 1;
}

int commit_fileSM (shmADT s, char * path, int type)
{
    int len, totlen;
    char msg[SHMSZ] = {0};
    char aux_msg[SHMSZ] = {0};
    char dir_path[FILE_LEN] = {0};
    int flag = 0, i;

    len = strlen (path);

    for (i = 0; i < len && flag < 2; i++)
    {
        dir_path[i] = path[i];

        if (path[i] == '/')
        {
            flag++;
        }
    }
    printf("path: %s\n",path);
    printf("Dir Path: %s\n", dir_path);
    sprintf(aux_msg, "%d,%s,%s,%d", getShmKey(privShm), usr_name, path, type);


    len = strlen(aux_msg);


    if (!canCommit (dir_path))
    {
        printf("Conflicts, can't commit\n");
        return 0;
    }

    sprintf(msg, "0,%d,%d,%d,%s", logged, COM_COMMIT, len, aux_msg);
    totlen = strlen (msg);

    send_data_shm(s, msg, totlen);

    return 1;
}

int listaSM (void)
{
    char msg[100] = {0};
    int len;

    len = strlen(usr_name);

    sprintf(msg, "0,%d,%d,%d,%d, %s", logged, COM_LIST, len, getShmKey(privShm), usr_name);
    send_data_shm(pub, msg, strlen(msg));

    return 1;
}

int agregarSM (void)
{
    int len;
    char msg[100] = {0};
    char dir[50] ={0};

    fprintf (stdout, "\nInsert a Dir: ");
    getLine (dir, MAX_COMMAND_LEN, stdin);

    len = strlen(dir);
    sprintf(msg, "0,%d,%d,%d,%d,%s,%s", logged, COM_ADD, len, getShmKey(privShm), usr_name, dir);
    send_data_shm(pub, msg, strlen(msg));

    return 1;
}

int removerSM (void)
{
    int len;
    char msg [100] = {0};
    char dir[MAX_DIR_LEN] = {0};

    fprintf (stdout, "\nInsert a Sync Dir: ");
    getLine (dir, MAX_DIR_LEN, stdin);

    len = strlen(dir);

    sprintf(msg, "0,%d,%d,%d,%d,%s,%s", logged, COM_REMOVE, len, getShmKey(privShm), usr_name, dir);
    send_data_shm(pub, msg, strlen(msg));

    return 1;
}

void
atenderRemoveSM(char * msg)
{
    int size, com;
    char dir[MAX_DIR_LEN] = {0};
    char w_dir[MAX_DIR_LEN] = {0};
    char r_msg[SHMSZ] = {0};

    sscanf(msg, "1,%d,%d,%s", &com, &size, dir);

    sprintf(w_dir,"./%s", dir);
    if ((remWatch(&w, w_dir)) == -1)
        fatal ("Couldn't remove watch of dir\n");

    clrtext(r_msg, SHMSZ);
    sprintf(r_msg, "0,%d", COM_ACK);
    send_data_shm(privShm, r_msg, strlen(r_msg));

    printf("OKOK!\n");

    return ;
}


int salirSM (void)
{
    char msg[100] = {0};

    if(logged)
    {
        sprintf(msg, "0,%d,%d,%d", logged, COM_CLOSE, getShmKey(privShm));
        send_data_shm(pub, msg, strlen(msg));
    }

    return 1;
}

void
closeAllSM(void)
{
    int i, stat;

    doLS = 0;

    if (logged)
    {
        salirSM();
        close_conn_shm(pub);
        if (splitVal == 't')
        {
            for( i = 0 ; i < SPLITS_QUANTITY ; i++)
            {
                pthread_join(threads[i], NULL);
            }
        }
        else
        {
            for( i = 0 ; i < SPLITS_QUANTITY ; i++)
            {
                kill(sons[i], SIGUSR1);
                waitpid (sons[i], &stat, 0);
            }
        }
    }
	
    exit(0);
    return;
}

void sighandINTSM(int signo)
{
    printf("\nSIGINT catched\n");
    closeAllSM();
}

void endCiclesSM(int signo)
{
    doLS = 0;

    return;
}

int commitSM(void)
{
    return 1;
}

int listenSM(void)
{
    int i;
    char msg[FILE_LEN] = {0};

    for(i = 0; i < 5; i++)
    {
        if(msgForClient(privShm))
        {
            rcv_data_shm(privShm, msg);
            return takeSrvSM(msg);
        }

        usleep(100);
    }
    return 0;
}

